package com.winit.schedule.job.tracker.repository.mongo;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.winit.schedule.core.conf.Configuration;
import com.winit.schedule.core.model.AssignedTask;
import com.winit.schedule.core.model.JobID;
import com.winit.schedule.core.model.TaskID;
import com.winit.schedule.core.repository.JobRepository;
import com.winit.schedule.core.repository.RepositoryEngine;
import com.winit.schedule.core.repository.TaskItemRepository;
import com.winit.schedule.core.repository.TaskRepository;
import com.winit.schedule.core.repository.TaskTrackerRepository;
import com.winit.schedule.core.repository.constants.JobStatus;
import com.winit.schedule.core.repository.constants.LogType;
import com.winit.schedule.core.repository.constants.TaskItemStatus;
import com.winit.schedule.core.repository.constants.TaskStatus;
import com.winit.schedule.core.repository.entity.QuartzJobEntity;
import com.winit.schedule.core.repository.entity.QuartzSchedulerEntity;
import com.winit.schedule.core.repository.entity.TaskEntity;
import com.winit.schedule.core.repository.entity.TaskItemEntity;
import com.winit.schedule.core.repository.entity.TaskRunRecordEntity;
import com.winit.schedule.core.repository.entity.TaskRunnerEntity;
import com.winit.schedule.core.repository.entity.TaskTrackerEntity;
import com.winit.schedule.core.repository.query.TaskItemQuery;
import com.winit.schedule.core.task.ScheduleTaskDefine;
import com.winit.schedule.core.utils.Clock;
import com.winit.schedule.core.utils.DateUtils;
import com.winit.schedule.job.tracker.repository.ScheduleDataManager;

public class MongoScheduleDataManager extends MongoLogDataManager implements ScheduleDataManager {

    private static transient final Logger logger = LoggerFactory.getLogger(MongoScheduleDataManager.class);

    private RepositoryEngine              repositoryEngine;

    private TaskTrackerRepository         taskTrackerRepository;

    private TaskRepository                taskRepository;

    private TaskItemRepository            taskItemRepository;

    private JobRepository                 jobRepository;

    public MongoScheduleDataManager(Configuration conf){
        repositoryEngine = new MongoRepositoryImpl(conf);
        taskTrackerRepository = repositoryEngine.getTaskTrackerRepository();
        taskRepository = repositoryEngine.getTaskRepository();
        taskItemRepository = repositoryEngine.getTaskItemRepository();
        loggerRepository = repositoryEngine.getLoggerRepository();
        jobRepository = repositoryEngine.getJobRepository();
    }

    @Override
    public TaskEntity getTaskEntityById(String taskId) {
        return taskRepository.getTaskEntityById(taskId);
    }

    @Override
    public TaskItemEntity findAndFetchTaskItemByTaskId(String taskTrackerUuid, String taskId, long nextRunTime,
                                                       int fetchNum) {
        return taskItemRepository.findAndFetchTaskItemByTaskId(taskTrackerUuid, taskId, nextRunTime, fetchNum);
    }

    @Override
    public long getTaskItemNumberOfPerTasktracker(String taskId) {
        int fetchNum = 1;
        long activiteTaskTrackerNum = taskTrackerRepository.queryTaskTackerNumberByTaskId(taskId);
        long taskItemNum = taskItemRepository.queyTaskItemNumByTaskId(taskId, Clock.getSystemTime());

        int val = (int) (taskItemNum / activiteTaskTrackerNum);

        if (taskItemNum % activiteTaskTrackerNum != 0) {
            val = val + 1;
        }

        return val > fetchNum ? val : fetchNum;
    }

    @Override
    public void recoveryPushFailureTaskItem(long timeout) {
        taskItemRepository.recoveryPushFailureTaskItem(timeout);
    }

    @Override
    public void removeTaskTrackerAndRunnerForTimeout(long heartbeatTimeout) {
        List<TaskTrackerEntity> entitys = taskTrackerRepository.removeTaskTrackerForTimeout(heartbeatTimeout);

        for (TaskTrackerEntity entity : entitys) {
            taskItemRepository.removeTaskRunnerByTaskTrackerUuid(entity.getTaskTrackerUuid());
            logger.info("The cleanup timeout TaskTracker, uuid: " + entity.getTaskTrackerUuid()
                        + ", Last heartbeat time: " + DateUtils.format(Clock.getDate(entity.getHeartbeatTime())));
        }

    }

    @Override
    public void removeTaskTrackerAndRunnerByUuid(String taskTrackerUuid) {
        taskItemRepository.removeTaskRunnerByTaskTrackerUuid(taskTrackerUuid);
        taskTrackerRepository.removeTaskTracker(taskTrackerUuid);
        logger(taskTrackerUuid, LogType.TASKTRACKER_DISCONNECT);
    }

    @Override
    public void updateTaskItemStatusByTaskRunnerUuid(TaskItemEntity taskItem) {

//        List<String> taskItemIds = null;
//        if (null != taskItems && !taskItems.isEmpty()) {
//            taskItemIds = new ArrayList<String>();
//            for (TaskItemEntity item : taskItems) {
//                taskItemIds.add(item.getTaskItemId());
//            }
//        }
//        taskItemRepository.completeTaskItemByTaskRunnerUuid(taskRunner.getTaskRunnerUuid(), taskItemIds, status);
    }

    @Override
    public TaskTrackerEntity getTaskTrackerByUuId(String uuid) {
        return taskTrackerRepository.getTaskTrackerByUuId(uuid);
    }

    @Override
    public TaskTrackerEntity saveOrUpdateTaskTrackerAndUpdateTaskInterfaceType(TaskTrackerEntity taskTracker) {

        // 更新tasktracker支持的任务接口类型
        List<TaskEntity> taskList = new ArrayList<TaskEntity>(taskTracker.getTaskDefines().size());
        for (ScheduleTaskDefine taskDefine : taskTracker.getTaskDefines()) {
            taskList.add(new TaskEntity(taskDefine.getGroup(), taskDefine.getTaskName(), taskDefine.getInterfaceType()));
        }
        taskRepository.updateTaskInterfaceType(taskList);
        // 更新taskTracker节点信息
        taskTracker = taskTrackerRepository.saveTaskTracker(taskTracker);
        return taskTracker;
    }

    @Override
    public TaskTrackerEntity updateHeartbeatTime(TaskTrackerEntity entity) {
        return taskTrackerRepository.updateHeartbeatTime(entity);
    }

    @Override
    public void updateTaskRunnerForTaskItem(TaskItemEntity taskItemEntity) {
        // taskItemRepository.updateTaskRunnerForTaskItem(runners);
    }

    @Override
    public List<TaskID> queryAllStopTaskIDs() {
        return taskRepository.queryAllStopTaskIDs();
    }

    @Override
    public void completeTask(TaskRunnerEntity taskRunner, AssignedTask task) {
//        taskRepository.updateTaskStatus(task.getTaskId().getTaskId(), TaskStatus.COMPLETE);
//
//        updateTaskItemStatusByTaskRunnerUuid(taskRunner, task.getTaskItems(), TaskItemStatus.COMPLETE);
//
//        JobID jobId = task.getTaskId().getJobId();
//        if (null != jobId) {
//            long unFinishedNum = taskRepository.queryUnfinishedTaskNumber(jobId.getJobId());
//            if (unFinishedNum == 0) {
//                jobRepository.updateJobStatus(task.getTaskId().getJobId(), JobStatus.COMPLETE);
//            }
//        }
    }

    @Override
    public void saveTaskRunRecord(TaskRunRecordEntity taskRunRecord) {
        // TODO Auto-generated method stub

    }

    @Override
    public void updateQuartzScheduler(List<QuartzSchedulerEntity> schedulers) {
        // TODO Auto-generated method stub

    }

    @Override
    public void deleteQuartzScheduler(String taskTrackerUuid) {
        // TODO Auto-generated method stub

    }

    @Override
    public void cleanQuartzCommand(String taskTrackerUuid) {
        // TODO Auto-generated method stub

    }

    @Override
    public List<QuartzJobEntity> queryJobCommnads(String taskTrackerUuid) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<QuartzSchedulerEntity> querySchedulerCommnads(String taskTrackerUuid) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void cleanQuartzTimeout(long timeout) {
        // TODO Auto-generated method stub

    }

    @Override
    public List<TaskItemEntity> queryTaskItemsByTimeout(TaskItemQuery query) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int deleteLogByLogtime(long logTime) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int deleteRunRecordByStarttime(long runStartTime) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void saveScheduleTaskDefine(ScheduleTaskDefine taskDefine, String taskTrackerUUID) {
        // TODO Auto-generated method stub
    }

    @Override public boolean containBlackList(String ipaddress) {
        return true;
    }

    @Override public boolean resetBlackListCache(String blackList) {
        return true;
    }

    @Override public List<TaskID> queryAllTaskIdByTaskTracker(String taskGroup) {
        return null;
    }

}
